package net.lab1024.sa.admin.module.device.terminal;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.device.terminal.constant.RemoteUrlConstant;
import net.lab1024.sa.admin.module.device.terminal.domain.DeviceTerminalEntity;
import net.lab1024.sa.admin.module.device.terminal.domain.DeviceTerminalQueryForm;
import net.lab1024.sa.admin.module.device.terminal.domain.DeviceTerminalVO;
import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.enumeration.EmployeeTypeEnum;
import net.lab1024.sa.base.common.exception.BusinessException;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class DeviceTerminalService {

    private final DeviceTerminalDao deviceTerminalDao;

    private final RestTemplate restTemplate;

    public DeviceTerminalService(DeviceTerminalDao deviceTerminalDao, RestTemplate restTemplate) {
        this.deviceTerminalDao = deviceTerminalDao;
        this.restTemplate = restTemplate;
    }

    /**
     * 批量保存终端设备信息
     * @param deviceTerminalEntityList 终端设备信息列表
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveDeviceTerminalBatch(List<DeviceTerminalEntity> deviceTerminalEntityList) {
        deviceTerminalDao.insertBatchSerialnos(deviceTerminalEntityList);
    }

    /**
     * 分页查询
     * @param queryForm 查询参数
     */
    public PageResult<DeviceTerminalVO> queryByPage(DeviceTerminalQueryForm queryForm, RequestEmployee requestUser) {
        Integer employeeType = requestUser.getEmployeeType();
        if (EmployeeTypeEnum.ENTERPRISE.getValue().equals(employeeType)) {
            queryForm.setEnterpriseId(requestUser.getEnterpriseId());
        }
        Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
        List<DeviceTerminalVO> list = deviceTerminalDao.queryPage(page, queryForm);
        return SmartPageUtil.convert2PageResult(page, list);
    }

    /**
     * 检查远程连接是否正常
     */
    public Boolean checkRemoteLink(String serialno) {
        // 测试请求，设备终端是否可以连接
        String testUrl = StrUtil.format(RemoteUrlConstant.Get.TEST_URL, serialno);
        boolean linkFlag;
        try {
            // 发送请求
            ResponseEntity<String> response = restTemplate.getForEntity(testUrl, String.class);
            // 返回成功与否的相应状态
            linkFlag = response.getStatusCode().series() == HttpStatus.Series.SUCCESSFUL;
        } catch (RestClientException e) {
            linkFlag = false;
            log.error("发送测试请求时出错", e);
        }
        // 更新连接状态
        deviceTerminalDao.updateLinkFlagBySerialno(serialno, linkFlag);
        log.info("设备终端的连接状态：{}", linkFlag);
        return linkFlag;
    }

    /**
     * 将时间之前的设备终端都标记为丢失
     */
    @Transactional(rollbackFor = Exception.class)
    public String lostByTimeAgo(LocalDateTime dateTime) {
        // 检查传入的时间
        if (Objects.isNull(dateTime)) {
            throw new BusinessException("传入的时间为空");
        }
        // 拿传入的时间和当前时间比较，传入的时间要在当前时间之前
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(dateTime)) {
            throw new BusinessException("传入的时间大于当前系统时间");
        }
        // 更新小于传入时间的连接状态为丢失
        int update = deviceTerminalDao.updateLinkFlagByHeartbeatTimeLt(dateTime, Boolean.FALSE);
        return StrUtil.format("标记为丢失的设备数量：{}", update);
    }

    /**
     * 根据设备序列号查询
     */
    public DeviceTerminalEntity getBySerialno(String serialno) {
        return deviceTerminalDao.getBySerialno(serialno);
    }

    /**
     * 根据设备序列号设置用户id
     */
    public void setUserIdBySerialno(Long userId, String serialno) {
        deviceTerminalDao.updateUserIdBySerialno(userId, serialno);
    }

    /**
     * 更新终端设备信息
     */
    public void update(DeviceTerminalEntity deviceTerminalEntity) {
        deviceTerminalDao.updateById(deviceTerminalEntity);
    }

    public String executeCommand(String serialno, String execType, String command) {
        // 先检查连接状态
        Boolean remoteLink = checkRemoteLink(serialno);

        if (!remoteLink) {
            return "设备连接丢失";
        }

        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        // 创建请求体
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("execType", execType);
        map.add("name", "sh");
        map.add("arg", "-c");
        map.add("arg", command);

        // 创建HttpEntity对象
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

        String url = StrUtil.format(RemoteUrlConstant.Post.COMMAND_DYNAMIC_URL, serialno);

        String failResponse = null;
        try {
            // 发送POST请求
            ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
            if (response.getStatusCode().series() != HttpStatus.Series.SUCCESSFUL) {
                failResponse = response.getBody();
            }
        } catch (Exception e) {
            log.error("发送执行部署命令请求时出错", e);
            failResponse = e.getMessage();
        }
        return failResponse;
    }
}
